#include "StreamPuller.h"
#include "MxBase/MemoryHelper/MemoryHelper.h"

AVFormatContext* CreateFormatContext(std::string filePath)
{
    LogInfo << "start to CreatFormatContext!";
    // creat message for stream pull
    AVFormatContext *formatContext = nullptr;
    AVDictionary *options = nullptr;

    LogInfo << "start to avformat_open_input!";    
    int ret = avformat_open_input(&formatContext, filePath.c_str(), nullptr, &options);
    if (options != nullptr)
    {
        av_dict_free(&options);
    }
    if (ret != 0)
    {
        LogError << "Couldn`t open input stream " << filePath.c_str() << " ret=" << ret;
        return nullptr;
    }
    ret = avformat_find_stream_info(formatContext, nullptr);
    if (ret != 0)
    {
        LogError << "Couldn`t open input stream information";
        return nullptr;
    }
    return formatContext;
}


APP_ERROR StreamPuller::Init() {
    std::string filePath = "";
    av_register_all();
    avformat_network_init();
    return APP_ERR_OK;
}

APP_ERROR StreamPuller::Process(const std::shared_ptr<void> &input) {
    AVPacket pkt;
    pFormatCtx_ = CreateFormatContext(*std::static_pointer_cast<std::string>(input));
    av_dump_format(pFormatCtx_, 0, std::static_pointer_cast<std::string>(input)->c_str(), 0);
    while(Status() == RunMode::RUNNING) {
        av_init_packet(&pkt);
        int ret = av_read_frame(pFormatCtx_, &pkt);
        if (ret != 0) {
            LogInfo << "[StreamPuller] channel Read frame failed, continue!";
            if (ret =+ AVERROR_EOF) 
            {
                LogInfo << "[StreamPuller] channel StreamPuller is EOF, over!";
                return ret;
            }
            return ret;
        } else {
            if (pkt.size <= 0) {
                LogError << "Invalid pkt.size: " << pkt.size;
                return APP_ERR_COMM_INVALID_PARAM;
            }    
            // send to the device 
            auto hostDeleter = [](void *dataPtr) { 
                delete []  dataPtr;
            };
            uint8_t *ptr = new uint8_t[pkt.size];
            std::copy((uint8_t*)pkt.data, (uint8_t*)pkt.data + pkt.size, ptr);
            std::shared_ptr<uint8_t> imageData((uint8_t*)ptr, hostDeleter);

            auto image = std::make_shared<Image>(imageData, pkt.size);
            SendData(image);
            av_packet_unref(&pkt);
            std::this_thread::sleep_for(std::chrono::milliseconds(40));
        }
    }
    return APP_ERR_OK;
}

APP_ERROR StreamPuller::DeInit() {
    avformat_close_input(&pFormatCtx_);
    return APP_ERR_OK;
}

std::string StreamPuller::GetModuleName() {
    return "StreamPuller";
}